#include "stdafx.h"
#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace NativeTest_Question31
{
	class Mystack
	{
	public:
		Mystack(int size);
		~Mystack();
		void Push(int index, int val);
		void Pop(int index);
		int Top(int index);
		bool Empty(int index);

	private:
		int lastones[3];
		int size;
		int* head;
	};
	Mystack::Mystack(int size)
	{
		head = new int[size *3];
		this->size = size;
		lastones[0] = lastones[1] = lastones[2] = -1;
	}
	Mystack::~Mystack()
	{
		if(head != NULL)
			delete[] head;
	}
	void Mystack::Push(int index, int val)
	{
		if(lastones[index] == size - 1 )
		{
			// renew array and copy array
		}

		++lastones[index] ;
		this->head[3*lastones[index] + index] = val;
		
	}
	void Mystack::Pop(int index)
	{
		if(!Empty(index))
		{
			--lastones[index];
		}
	}
	int Mystack::Top(int index)
	{
		if(!Empty(index))
		{
			return head[3* lastones[index] + index];
		}
		else
		{
			return INT32_MIN;
		}
	}
	bool Mystack::Empty(int index)
	{
		return lastones[index] == -1;
	}


	typedef struct node{
		int val;
		int preindex;
	} node;

	class MystackInNode
	{
	public:
		MystackInNode(int size);
		~MystackInNode();
		void Push(int index, int val);
		void Pop(int index);
		int Top(int index);
		bool Empty(int index);
	private:
		node* head;
		int size;
		int lastindex;
		int lastones[3];
	};

	MystackInNode::MystackInNode(int size)
	{
		head = new node[size];
		this->size = size;
		lastindex = -1;
		lastones[0] = lastones[1] = lastones[2] = -1;
	}

	MystackInNode::~MystackInNode()
	{
		delete[] head;
	}

	void MystackInNode::Push(int index, int val)
	{
		++lastindex;
		if(lastindex == size)
		{
			// renew array and copy
		}
		head[lastindex].val = val;
		head[lastindex].preindex = lastones[index];
		lastones[index] = lastindex;
	}

	void MystackInNode::Pop(int index)
	{
		if(!Empty(index))
		{
			lastones[index] = head[lastones[index]].preindex;
		}
	}

	int MystackInNode::Top(int index)
	{
		if(!Empty(index))
		{
			return head[lastones[index]].val;
		}
		else
		{
			return INT32_MIN;
		}
	}
	
	bool MystackInNode::Empty(int index)
	{
		return lastones[index] == -1;
	}
}
namespace NativeTest
{

	using namespace NativeTest_Question31;

	TEST_CLASS(Question31)
	{
	public:
		
		TEST_METHOD(Question31_TestMethod1)
		{
			Mystack* s = new Mystack(10);
			Assert::IsTrue(s->Empty(0));
			s->Push(0, 1);
			Assert::AreEqual(1, s->Top(0));
			s->Push(0, 2);
			Assert::AreEqual(2, s->Top(0));
			s->Push(0, 3);
			Assert::AreEqual(3, s->Top(0));
			s->Push(0, 4);
			Assert::AreEqual(4, s->Top(0));
			s->Push(0, 5);
			Assert::AreEqual(5, s->Top(0));
			s->Push(0, 6);
			Assert::AreEqual(6, s->Top(0));

			s->Pop(0); Assert::AreEqual(5, s->Top(0));
			s->Pop(0); Assert::AreEqual(4, s->Top(0));
			s->Pop(0); Assert::AreEqual(3, s->Top(0));
			s->Pop(0); Assert::AreEqual(2, s->Top(0));
			s->Pop(0); Assert::AreEqual(1, s->Top(0));
			s->Pop(0); Assert::AreEqual(INT32_MIN, s->Top(0));
			s->Pop(0); Assert::AreEqual(INT32_MIN, s->Top(0));
			Assert::IsTrue(s->Empty(0));

			Assert::IsTrue(s->Empty(1));
			s->Push(1, 1);
			Assert::AreEqual(1, s->Top(1));
			s->Push(1, 2);
			Assert::AreEqual(2, s->Top(1));
			s->Push(1, 3);
			Assert::AreEqual(3, s->Top(1));
			s->Push(1, 4);
			Assert::AreEqual(4, s->Top(1));
			s->Push(1, 5);
			Assert::AreEqual(5, s->Top(1));
			s->Push(1, 6);
			Assert::AreEqual(6, s->Top(1));

			s->Pop(1); Assert::AreEqual(5, s->Top(1));
			s->Pop(1); Assert::AreEqual(4, s->Top(1));
			s->Pop(1); Assert::AreEqual(3, s->Top(1));
			s->Pop(1); Assert::AreEqual(2, s->Top(1));
			s->Pop(1); Assert::AreEqual(1, s->Top(1));
			s->Pop(1); Assert::AreEqual(INT32_MIN, s->Top(1));
			s->Pop(1); Assert::AreEqual(INT32_MIN, s->Top(1));
			Assert::IsTrue(s->Empty(1));

			Assert::IsTrue(s->Empty(2));
			s->Push(2, 1);
			Assert::AreEqual(1, s->Top(2));
			s->Push(2, 2);
			Assert::AreEqual(2, s->Top(2));
			s->Push(2, 3);
			Assert::AreEqual(3, s->Top(2));
			s->Push(2, 4);
			Assert::AreEqual(4, s->Top(2));
			s->Push(2, 5);
			Assert::AreEqual(5, s->Top(2));
			s->Push(2, 6);
			Assert::AreEqual(6, s->Top(2));

			s->Pop(2); Assert::AreEqual(5, s->Top(2));
			s->Pop(2); Assert::AreEqual(4, s->Top(2));
			s->Pop(2); Assert::AreEqual(3, s->Top(2));
			s->Pop(2); Assert::AreEqual(2, s->Top(2));
			s->Pop(2); Assert::AreEqual(1, s->Top(2));
			s->Pop(2); Assert::AreEqual(INT32_MIN, s->Top(2));
			s->Pop(2); Assert::AreEqual(INT32_MIN, s->Top(2));
			Assert::IsTrue(s->Empty(2));
		}

		TEST_METHOD(Question31_TestMethod2)
		{
			MystackInNode* s = new MystackInNode(30);
			Assert::IsTrue(s->Empty(0));
			s->Push(0, 1);
			Assert::AreEqual(1, s->Top(0));
			s->Push(0, 2);
			Assert::AreEqual(2, s->Top(0));
			s->Push(0, 3);
			Assert::AreEqual(3, s->Top(0));
			s->Push(0, 4);
			Assert::AreEqual(4, s->Top(0));
			s->Push(0, 5);
			Assert::AreEqual(5, s->Top(0));
			s->Push(0, 6);
			Assert::AreEqual(6, s->Top(0));

			s->Pop(0); Assert::AreEqual(5, s->Top(0));
			s->Pop(0); Assert::AreEqual(4, s->Top(0));
			s->Pop(0); Assert::AreEqual(3, s->Top(0));
			s->Pop(0); Assert::AreEqual(2, s->Top(0));
			s->Pop(0); Assert::AreEqual(1, s->Top(0));
			s->Pop(0); Assert::AreEqual(INT32_MIN, s->Top(0));
			s->Pop(0); Assert::AreEqual(INT32_MIN, s->Top(0));
			Assert::IsTrue(s->Empty(0));

			Assert::IsTrue(s->Empty(1));
			s->Push(1, 1);
			Assert::AreEqual(1, s->Top(1));
			s->Push(1, 2);
			Assert::AreEqual(2, s->Top(1));
			s->Push(1, 3);
			Assert::AreEqual(3, s->Top(1));
			s->Push(1, 4);
			Assert::AreEqual(4, s->Top(1));
			s->Push(1, 5);
			Assert::AreEqual(5, s->Top(1));
			s->Push(1, 6);
			Assert::AreEqual(6, s->Top(1));

			s->Pop(1); Assert::AreEqual(5, s->Top(1));
			s->Pop(1); Assert::AreEqual(4, s->Top(1));
			s->Pop(1); Assert::AreEqual(3, s->Top(1));
			s->Pop(1); Assert::AreEqual(2, s->Top(1));
			s->Pop(1); Assert::AreEqual(1, s->Top(1));
			s->Pop(1); Assert::AreEqual(INT32_MIN, s->Top(1));
			s->Pop(1); Assert::AreEqual(INT32_MIN, s->Top(1));
			Assert::IsTrue(s->Empty(1));

			Assert::IsTrue(s->Empty(2));
			s->Push(2, 1);
			Assert::AreEqual(1, s->Top(2));
			s->Push(2, 2);
			Assert::AreEqual(2, s->Top(2));
			s->Push(2, 3);
			Assert::AreEqual(3, s->Top(2));
			s->Push(2, 4);
			Assert::AreEqual(4, s->Top(2));
			s->Push(2, 5);
			Assert::AreEqual(5, s->Top(2));
			s->Push(2, 6);
			Assert::AreEqual(6, s->Top(2));

			s->Pop(2); Assert::AreEqual(5, s->Top(2));
			s->Pop(2); Assert::AreEqual(4, s->Top(2));
			s->Pop(2); Assert::AreEqual(3, s->Top(2));
			s->Pop(2); Assert::AreEqual(2, s->Top(2));
			s->Pop(2); Assert::AreEqual(1, s->Top(2));
			s->Pop(2); Assert::AreEqual(INT32_MIN, s->Top(2));
			s->Pop(2); Assert::AreEqual(INT32_MIN, s->Top(2));
			Assert::IsTrue(s->Empty(2));
		}
	};
}